/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.helper;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagraminterchange2.di2.Di2Factory;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Factory that gives a basic implementation of the {@link IGraphElementHelper} interface.
 * 
 * @author Remi Schnekenburger
 */
public class NodeHelper implements IGraphElementHelper {

	/**
	 * The Constant NODE_FIGURE_APPEARANCE.
	 */
	public final static String NODE_FIGURE_APPEARANCE = "NodeFigureAppearance";
	
	/**
	 * 
	 */
	public static int number=0;

	/**
	 * Debug channel.
	 */
	protected static int channel=15;

	/**
	 * {@inheritDoc}
	 */
	public GraphNode createGraphElement(Element umlChild, GraphElement parent, Point location, Dimension size){

		//create GraphNode
		GraphNode graphNode=Di2Factory.eINSTANCE.createGraphNode();
		graphNode.setIsVisible(true);
		setGraphElementPreferences(graphNode);
		graphNode.setLineStyle("solid");
		graphNode.setLineThickness(1);
		graphNode.setForegroundColor(new RGB(248,249,214));//yellow


		if(location!=null){
			graphNode.setPosition(location);
		}
		else{
			graphNode.setPosition(new Point(20, 20));
		}

		if (size!=null){
			graphNode.setSize(size);
		}
		else{
			graphNode.setSize(getGraphNodeSize());
		}

		if (umlChild!=null){
			//	createUMLbridgee
			Uml1SemanticModelBridge semantic= Di2Factory.eINSTANCE.createUml1SemanticModelBridge();
			// set default presenation (text stereotype)
			semantic.setPresentation(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION);
			//associate semantic with graphNode
			graphNode.setSemanticModel(semantic);
			semantic.setElement(umlChild);
		}
		if( parent!=null){
			parent.getContained().add(graphNode);
		}
		return graphNode;
	}

	/**
	 * {@inheritDoc}
	 */
	public void setGraphElementPreferences(GraphElement graphElement) {
		graphElement.setBackgroundColor(new RGB(248,249,214));//yellow
		graphElement.setBorderColor(new RGB(157,124,47));//brown
		graphElement.setFontColor(new RGB(0,0,0));//black
		graphElement.setFontFamily("Arial");
		graphElement.setFontSize(10);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean canCreateGraphElement(GraphElement parent) {
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean removeGraphElement(GraphElement child, GraphElement parent){
		if( child.getContainer()!=null){
			return child.getContainer().getContained().remove(child);
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public GraphElement addGraphElement(GraphElement child, GraphElement parent) {
		parent.getContained().add(child);
		return child;
	}

	/**
	 * {@inheritDoc}
	 */
	public ArrayList createGraphNode(Element umlElement, Diagram diagram) {

		//Debug.debug(this,"Call ModelResourceManager.createGraphNode() pour "+ umlElement.getClass()+ " dans "+diagram.getName(), debugChannel);


		//look for graphNode of the umlElement parent
		ArrayList parentGraphNode= LookForElement.lookForGraphElement(umlElement.getOwner(), diagram, new ArrayList());
		Iterator it =parentGraphNode.iterator();
		ArrayList createdNode=new ArrayList();
		if (parentGraphNode.size()!=0){
			while(it.hasNext()){
				//current node
				GraphNode currentNode=(GraphNode)it.next();

				//node creation
				GraphNode graphNode=Di2Factory.eINSTANCE.createGraphNode();
				setGraphElementPreferences(graphNode);
				graphNode.setLineStyle("solid");
				graphNode.setLineThickness(1);
				graphNode.setForegroundColor(new RGB(248,249,214));//yellow
				graphNode.setIsVisible(true);
				graphNode.setPosition(new Point(20, 20));
				graphNode.setSize(getGraphNodeSize());
				//createUMLbridgee
				Uml1SemanticModelBridge semantic= Di2Factory.eINSTANCE.createUml1SemanticModelBridge();
				// set default presenation (text stereotype)
				semantic.setPresentation(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION);

				//associate semantic with graphNode
				graphNode.setSemanticModel(semantic);
				/*if (umlElement instanceof ElementImport){
					semantic.setElement(((ElementImport)umlElement).getImportedElement());
				}
				else{semantic.setElement(umlElement);}*/
				semantic.setElement(umlElement);
				//add the node
				currentNode.getContained().add(graphNode);
				createdNode.add(graphNode);

			}
		}
		else{
			// node creation
			GraphNode graphNode=Di2Factory.eINSTANCE.createGraphNode();
			graphNode.setIsVisible(true);	
			setGraphElementPreferences(graphNode);
			graphNode.setLineStyle("solid");
			graphNode.setLineThickness(1);
			graphNode.setForegroundColor(new RGB(248,249,214));//yellow
			graphNode.setPosition(new Point(20, 20));
			graphNode.setSize(getGraphNodeSize());
			//createUMLbridgee
			Uml1SemanticModelBridge semantic= Di2Factory.eINSTANCE.createUml1SemanticModelBridge();
			// set default presentation (text stereotype)
			semantic.setPresentation(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION);

			//associate semantic with graphNode
			graphNode.setSemanticModel(semantic);
			semantic.setElement(umlElement);
			//add the node
			diagram.getContained().add(graphNode);
			createdNode.add(graphNode);

		}
		return createdNode;
	}


	/**
	 * {@inheritDoc}
	 */
	public org.eclipse.uml2.uml.Element createUMLElement(String name, org.eclipse.uml2.uml.Element umlParent){
		return null;		
	}

	/**
	 * {@inheritDoc}
	 */
	public org.eclipse.uml2.uml.Element createUMLElement(org.eclipse.uml2.uml.Element umlParent){
		return createUMLElement(getNewUMLElementName(umlParent), umlParent);
	}


	/**
	 * {@inheritDoc}
	 */
	public boolean canCreateUMLElement(Element umlParent) {
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean addUMLElement(Element element, Element umlParent) {
		return umlParent.getOwnedElements().add(element);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean removeUMLElement(Element element, Element umlParent) {
		return umlParent.getOwnedElements().remove(element);
	}
	
	/**
	 * Generic method that returns a new unique name within a namespace.
	 * 
	 * @param umlParent the parent of the element to create
	 * 
	 * @return a distinguisable name within the namespace of the umlParent
	 */
	public String getNewUMLElementName(Element umlParent) {
		String name = ""; //$NON-NLS-1$

		boolean found = false;
		// i <10000: avoid infinite loops
		for(int i=0; i< 10001; i++ ) {
			found = false;
			name = getBaseString()+i;
			Iterator it = umlParent.getOwnedElements().iterator();
			while(it.hasNext() && !found) {
				Object o = it.next();
				if(o instanceof NamedElement) {
					if(name.equals(((NamedElement)o).getName())) {
						found = true;
					}
				}
			}
			if(!found) {
				return name;
			}
		}
		return getBaseString()+"X"; //$NON-NLS-1$
	}

	/**
	 * {@inheritDoc}
	 */
	public String getBaseString() {
		return "default"; //$NON-NLS-1$
	}

	/**
	 * Gets the graph node size.
	 * 
	 * @return the graph node size
	 */
	public Dimension getGraphNodeSize() {
		return new Dimension(100,100);
	}

}
